﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using ezCloud.Data;
using Microsoft.AspNet.Identity;
using ezCloud.Api.Models;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OAuth;
using ezCloud.Api.Providers;
using ezCloud.Api.Results;
using System.Web.Http.ModelBinding;
using System.Security.Claims;
using System.Web.Script.Serialization;
using System.Collections.ObjectModel;
using ezCloud.Api.Common;
using System.Data.SqlTypes;
using Nest;
using CodeSmith.Data.Audit;
using System.Reflection;
using System.Configuration;

namespace ezCloud.Api.Controllers
{
    [ApiAuthorize(Roles = "ROLE_HOTEL_OWNER,ROLE_HOTEL_MANAGER")]
    [RoutePrefix("api/AuditTrail")]
    public class AuditTrailController : ezController
    {

        public class AuditTrailSearchModel
        {
            public DateTime From { get; set; }
            public DateTime To { get; set; }
            public string UserId { get; set; }
            public string Operation { get; set; }
            public int RoomId { get; set; }
            public int? ReservationNumber { get; set; }
        }

        public class AuditLogInformation
        {
            public string Operation { get; set; }
            public int ReservationNumber { get; set; }
            public int Id { get; set; }
            public string Guest { get; set; }
            public string RoomNo { get; set; }
            public Dictionary<string, string> Particular { get; set; }
            public string User { get; set; }
            public DateTime DateTime { get; set; }
            //public Dictionary<string,string> 
        }




        public AuditTrailController()
        {
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("GetAllSearchData")]
        public async Task<IHttpActionResult> GetAllUser()
        {
            var user = Common.UserUtitily.getUserProfile();
            var allUser = context.AspNetUsers.Where(usr => usr.DefaultHotelId == user.HotelId).ToList();
            var allRoom = context.Rooms.Where(rm => rm.HotelId == user.HotelId)
                .Select(r => new
                {
                    r.RoomId,
                    r.RoomName
                }).ToList();
            return Ok(new
            {
                allUser = allUser,
                allRoom = allRoom
            });
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("ProcessSearch")]
        public async Task<IHttpActionResult> ProcessSearch(AuditTrailSearchModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            // RESOLVE SEARCH RESULT

            var returnResult = new List<AuditLogInformation>();
            if (model.Operation != "ALL")
            {
                if (model.Operation == "UPDATE_RESERVATION")
                {
                    returnResult.AddRange(resolveSearchResult(model, "CHANGE_NOTE"));
                    returnResult.AddRange(resolveSearchResult(model, "CHANGE_REMARK"));
                    returnResult.AddRange(resolveSearchResult(model, "CHANGE_ASSIGN_ROOM"));
                }
                returnResult = resolveSearchResult(model, model.Operation);
            }
            else
            {
                if (resolveSearchResult(model, "ADD_PAYMENT").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "ADD_PAYMENT"));
                }
                if (resolveSearchResult(model, "VOID_PAYMENT").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "VOID_PAYMENT"));
                }
                if (resolveSearchResult(model, "ADD_MINIBAR").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "ADD_MINIBAR"));
                }
                if (resolveSearchResult(model, "VOID_MINIBAR").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "VOID_MINIBAR"));
                }
                if (resolveSearchResult(model, "ADD_LAUNDRY").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "ADD_LAUNDRY"));
                }
                if (resolveSearchResult(model, "VOID_LAUNDRY").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "VOID_LAUNDRY"));
                }
                if (resolveSearchResult(model, "ADD_COMPENSATION").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "ADD_COMPENSATION"));
                }
                if (resolveSearchResult(model, "VOID_COMPENSATION").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "VOID_COMPENSATION"));
                }
                if (resolveSearchResult(model, "ADD_EXTRA_SERVICE").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "ADD_EXTRA_SERVICE"));
                }
                if (resolveSearchResult(model, "VOID_EXTRA_SERVICE").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "VOID_EXTRA_SERVICE"));
                }
                if (resolveSearchResult(model, "CHECKIN").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "CHECKIN"));
                }
                if (resolveSearchResult(model, "CHECKOUT").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "CHECKOUT"));
                }
                if (resolveSearchResult(model, "NOSHOW").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "NOSHOW"));
                }
                if (resolveSearchResult(model, "BOOKED").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "BOOKED"));
                }
                if (resolveSearchResult(model, "CANCELLED").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "CANCELLED"));
                }
                if (resolveSearchResult(model, "AMEND_STAY").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "AMEND_STAY"));
                }
                if (resolveSearchResult(model, "ROOM_MOVE").Count > 0)
                {
                    returnResult.AddRange(resolveSearchResult(model, "ROOM_MOVE"));
                }


            }
            return Ok(returnResult);
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("ProcessSearchConfiguration")]
        public async Task<IHttpActionResult> ProcessSearchConfiguration(AuditTrailSearchModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            // RESOLVE SEARCH RESULT

            var returnResult = new List<AuditLogInformation>();
            returnResult = resolveSearchConfigurationResult(model, model.Operation);

            return Ok(returnResult);
        }

        public List<AuditLogInformation> resolveSearchResult(AuditTrailSearchModel model, string operation)
        {

            var user = Common.UserUtitily.getUserProfile();
            var currentHotel = context.Hotels.Where(ht => ht.HotelId == user.HotelId).FirstOrDefault();
            var node = new Uri("http://localhost:9200");
            var settings = new ConnectionSettings(
                    node,
                    defaultIndex: ConfigurationSettings.AppSettings["elasticIndex"]
                );
            var client = new ElasticClient(settings);

            var searchDescriptor = new SearchDescriptor<AuditLog>();
            searchDescriptor.Index(ConfigurationSettings.AppSettings["elasticIndex"]).Types("auditlogs").From(0).Size(1000);
            var filters = new List<FilterContainer>();
            filters.Add(new FilterDescriptor<AuditLog>().Term("entities.current.hotelId", user.HotelId));

            // SEARCH FOR FROM-TO
            var timeZoneOffset = -currentHotel.TimeZoneOffset / 60;
            TimeSpan offSet = new TimeSpan(timeZoneOffset, 0, 0);
            if (model.From == null)
            {
                model.From = ((DateTime)SqlDateTime.MinValue).Date;
            }
            if (model.To == null)
            {
                model.To = ((DateTime)SqlDateTime.MaxValue).Date;
            }
            if (model.From != null)
            {
                DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.From).Year, ((DateTime)model.From).Month, ((DateTime)model.From).Day, ((DateTime)model.From).Hour, ((DateTime)model.From).Minute, ((DateTime)model.From).Second, offSet).ToOffset(TimeSpan.Zero);
                //model.From = fromTemp.Date;
                model.From = model.From.AddHours(currentHotel.TimeZoneOffset / 60).Date;
            }
            if (model.To != null)
            {
                DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.To).Year, ((DateTime)model.To).Month, ((DateTime)model.To).Day, ((DateTime)model.To).Hour, ((DateTime)model.To).Minute, ((DateTime)model.To).Second, offSet).ToOffset(TimeSpan.Zero);
                //model.To = toTemp.Date;
                model.To = model.To.AddHours(currentHotel.TimeZoneOffset / 60).Date.AddDays(1);
            }

            filters.Add(new FilterDescriptor<AuditLog>().Range(r => r.OnField(f => f.Date).GreaterOrEquals(model.From).LowerOrEquals(model.To)));

            // SEARCH FOR USER
            var userName = "";
            QueryContainer userQuery = new QueryContainer();
            if (model.UserId != null)
            {
                var userTemp = context.AspNetUsers.Where(u => u.DefaultHotelId == user.HotelId && u.Id == model.UserId).FirstOrDefault();
                if (userTemp != null)
                {
                    userName = userTemp.UserName;
                    filters.Add(new FilterDescriptor<AuditLog>().Bool(b => b.Must(m => m.Query(q => q.Match(mat => mat.OnField(z => z.Username).Query(userName))))));
                }
            }

            // SEARCH FOR RES NO
            if (model.ReservationNumber > 0)
            {
                var reservation = context.Reservations.Where(r => r.HotelId == user.HotelId && r.ReservationNumber == model.ReservationNumber).FirstOrDefault();
                if (reservation != null)
                {
                    var reservationRoom = context.ReservationRooms.Where(rr => rr.HotelId == user.HotelId && rr.ReservationId == reservation.ReservationId).FirstOrDefault();
                    filters.Add(new FilterDescriptor<AuditLog>().Term("entities.current.reservationRoomId", reservationRoom.ReservationRoomId));
                }

            }

            // SEARCH FOR ROOM NO
            if (model.RoomId > 0)
            {
                var reservationRooms = context.ReservationRooms.Where(rr => rr.HotelId == user.HotelId && rr.RoomId == model.RoomId).ToList();
                List<string> reservationRoomIds = new List<string>();
                foreach (var rr in reservationRooms)
                {
                    if (rr != null)
                    {
                        reservationRoomIds.Add(rr.ReservationRoomId.ToString());
                    }
                }
                filters.Add(new FilterDescriptor<AuditLog>().Terms("entities.current.reservationRoomId", reservationRoomIds));
            }

            FilterContainer reservationRoomFilter = new FilterDescriptor<AuditLog>().Bool(b => b.Must(m => m.Query(q => q.Match(mat => mat.OnField(z => z.Entities.First().Type).Query("ezCloud.Data.ReservationRooms")))));
            FilterContainer paymentFilter = new FilterDescriptor<AuditLog>().Bool(b => b.Must(m => m.Query(q => q.Match(mat => mat.OnField(z => z.Entities.First().Type).Query("ezCloud.Data.Payments")))));
            FilterContainer roomExtraServiceFilter = new FilterDescriptor<AuditLog>().Bool(b => b.Must(m => m.Query(q => q.Match(mat => mat.OnField(z => z.Entities.First().Type).Query("ezCloud.Data.RoomExtraServices")))));

            FilterContainer insertRRFilter = new FilterDescriptor<AuditLog>().Bool(b => b.Must(m => m.Query(q => q.Match(mat => mat.OnField(z => z.Entities.First().Action).Query("1")))));
            FilterContainer updateRRFilter = new FilterDescriptor<AuditLog>().Bool(b => b.Must(m => m.Query(q => q.Match(mat => mat.OnField(z => z.Entities.First().Action).Query("2")))));
            switch (operation)
            {
                case "ADD_PAYMENT":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.paymentId"));
                    filters.Add(new FilterDescriptor<AuditLog>().Missing("entities.original"));
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.paymentTypeName'].value != 'deleted'")));
                    break;
                case "VOID_PAYMENT":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.paymentId"));
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.refPaymentId"));
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.paymentTypeName'].value == 'deleted'")));
                    break;
                case "AMEND_STAY":
                    filters.Add(reservationRoomFilter);
                    filters.Add(updateRRFilter);
                    filters.Add(new FilterDescriptor<AuditLog>().Bool(bq => bq.Should(shd => shd.Script(sq1 => sq1.Script("doc['entities.current.departureDate'].value != doc['entities.original.departureDate'].value")), shd => shd.Script(sq2 => sq2.Script("doc['entities.current.arrivalDate'].value != doc['entities.original.arrivalDate'].value")))));
                    break;
                case "ROOM_MOVE":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.roomMoveId"));
                    break;
                case "CHECKIN":
                    filters.Add(new FilterDescriptor<AuditLog>().Missing("entities.current.roomMoveId"));
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.bookingStatus'].value == 'checkin'")));
                    break;
                case "CHECKOUT":
                    filters.Add(reservationRoomFilter);
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.bookingStatus'].value == 'checkout'")));
                    break;
                case "BOOKED":
                    filters.Add(reservationRoomFilter);
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.bookingStatus'].value == 'booked'")));
                    filters.Add(new FilterDescriptor<AuditLog>().Range(r => r.OnField("entities.current.arrivalDate").Greater(DateTime.UtcNow)));
                    break;
                case "CANCELLED":
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.bookingStatus'].value == 'cancelled'")));
                    break;
                case "NOSHOW":
                    filters.Add(reservationRoomFilter);
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.bookingStatus'].value == 'booked'")));
                    filters.Add(new FilterDescriptor<AuditLog>().Range(r => r.OnField("entities.current.arrivalDate").LowerOrEquals(DateTime.UtcNow)));
                    break;
                case "ADD_MINIBAR":
                    filters.Add(roomExtraServiceFilter);
                    filters.Add(new FilterDescriptor<AuditLog>().Strict().Script(sq1 => sq1.Script("doc['entities.current.roomExtraServiceName'].value == 'minibar'")));
                    break;
                case "VOID_MINIBAR":
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.roomExtraServiceName'].value == 'minibar'")));
                    filters.Add(new FilterDescriptor<AuditLog>().Term("entities.current.isDeleted", true));
                    break;
                case "ADD_LAUNDRY":
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.roomExtraServiceName'].value == 'laundry'")));
                    break;
                case "VOID_LAUNDRY":
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.roomExtraServiceName'].value == 'laundry'")));
                    filters.Add(new FilterDescriptor<AuditLog>().Term("entities.current.isDeleted", true));
                    break;
                case "ADD_COMPENSATION":
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.roomExtraServiceName'].value == 'compensation'")));
                    break;
                case "VOID_COMPENSATION":
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.roomExtraServiceName'].value == 'compensation'")));
                    filters.Add(new FilterDescriptor<AuditLog>().Term("entities.current.isDeleted", true));

                    break;

                case "ADD_EXTRA_CHARGE":
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.roomExtraServiceName'].value == 'extra_charge'")));
                    break;
                case "VOID_EXTRA_CHARGE":
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.roomExtraServiceName'].value == 'extra_charge'")));
                    filters.Add(new FilterDescriptor<AuditLog>().Term("entities.current.isDeleted", true));

                    break;

                case "ADD_EXTRA_SERVICE":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.roomExtraServiceNumber"));
                    filters.Add(new FilterDescriptor<AuditLog>().Missing("entities.current.roomExtraServiceItemId"));
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.roomExtraServiceName'].value == 'extra_services'")));
                    break;

                case "VOID_EXTRA_SERVICE":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.roomExtraServiceNumber"));
                    filters.Add(new FilterDescriptor<AuditLog>().Missing("entities.current.roomExtraServiceItemId"));
                    filters.Add(new FilterDescriptor<AuditLog>().Script(sq1 => sq1.Script("doc['entities.current.roomExtraServiceName'].value == 'extra_services'")));
                    filters.Add(new FilterDescriptor<AuditLog>().Term("entities.current.isDeleted", true));
                    break;

                case "GUEST_CHANGE/ADD":

                    break;
                case "PAST_CHECKOUT":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.pastCheckOutId"));
                    break;
                case "UPDATE_RESERVATION":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.reservationRoomId"));
                    filters.Add(new FilterDescriptor<AuditLog>().Bool(bq => bq.Must(mq => mq.Query(q => q.Match(m => m.OnField("entities.properties.name").Query("note"))))));
                    break;
                case "PRE_CHECKIN":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.changeReservationStatusId"));
                    filters.Add(new FilterDescriptor<AuditLog>().Bool(bq => bq.Must(mq => mq.Query(q => q.Match(m => m.OnField("entities.current.actionCode").Query("pre_checkin"))))));
                    break;
                case "PRE_CHECKOUT":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.changeReservationStatusId"));
                    filters.Add(new FilterDescriptor<AuditLog>().Bool(bq => bq.Must(mq => mq.Query(q => q.Match(m => m.OnField("entities.current.actionCode").Query("pre_checkout"))))));
                    break;
            }
            searchDescriptor.Filter(f => f.And(filters.ToArray()));
            searchDescriptor.SortDescending("date");
            var search = client.Search<AuditLog>(
                   searchDescriptor
               );
            var result = search.Documents;
            List<AuditLogInformation> returnResult = new List<AuditLogInformation>();
            if (result.Count() > 0)
            {
                string format = "dd/MM/yyyy, hh:mm";
                foreach (var item in result)
                {
                    var auditUserName = item.Username;
                    var auditDateTime = item.Date;
                    if (item.Entities != null && item.Entities.Count > 0)
                    {
                        // COUNT _Number IN ITEM ENTITIES
                        var numberCount = 0;
                        foreach (var entity in item.Entities)
                        {
                            JObject entityJObject = JObject.Parse(entity.Current.ToString());
                            foreach (var propObj in entityJObject.Properties())
                            {
                                if (propObj.Name.EndsWith("Number"))
                                {
                                    numberCount += 1;
                                }
                            }
                        }
                        if (numberCount == 1)
                        {
                            int reservationRoomId = 0;
                            foreach (var entity in item.Entities)
                            {
                                JObject original = new JObject();
                                if (entity.Original != null)
                                {
                                    original = JObject.Parse(entity.Original.ToString());
                                }
                                JObject obj = JObject.Parse(entity.Current.ToString());
                                if (obj.Property("reservationRoomId") != null)
                                {
                                    reservationRoomId = (int)obj["reservationRoomId"];
                                    var reservationRoom = context.ReservationRooms.Where(rr => rr.HotelId == user.HotelId && rr.ReservationRoomId == reservationRoomId).FirstOrDefault();
                                    var reservation = context.Reservations.Where(r => r.HotelId == user.HotelId && r.ReservationId == reservationRoom.ReservationId).FirstOrDefault();
                                    var room = context.Rooms.Where(rm => rm.HotelId == user.HotelId && rm.RoomId == reservationRoom.RoomId).FirstOrDefault();
                                    var roomType = context.RoomTypes.Where(rt => rt.HotelId == user.HotelId && rt.RoomTypeId == reservationRoom.RoomTypeId).FirstOrDefault();
                                    var roomPrice = context.RoomPrices.Where(rp => rp.HotelId == user.HotelId && rp.RoomPriceId == reservationRoom.RoomPriceId).FirstOrDefault();
                                    var traveller = context.Travellers.Where(tvl => tvl.TravellerId == (context.ReservationTravellers.Where(rt => rt.ReservationRoomId == reservationRoom.ReservationRoomId && rt.TravellerId == reservationRoom.TravellerId).FirstOrDefault().TravellerId)).FirstOrDefault();
                                    AuditLogInformation info = new AuditLogInformation();
                                    info.ReservationNumber = reservation.ReservationNumber ?? 0;
                                    info.RoomNo = room.RoomName;
                                    info.Guest = traveller.Fullname;
                                    info.Operation = operation;
                                    info.Particular = new Dictionary<string, string>();
                                    info.User = auditUserName;
                                    info.DateTime = auditDateTime;
                                    bool hasNumber = false;
                                    var properties = obj.Properties();
                                    foreach (var propObj in properties)
                                    {
                                        if (propObj.Name.EndsWith("Number"))
                                        {
                                            hasNumber = true;
                                        }
                                    }
                                    if (hasNumber)
                                    {
                                        switch (operation)
                                        {
                                            case "ADD_PAYMENT":
                                            case "VOID_PAYMENT":
                                                info.Id = (int)obj["paymentNumber"];
                                                var paymentMethodName = context.PaymentMethods.Where(pm => pm.PaymentMethodId == (int)obj["paymentMethodId"]).FirstOrDefault().PaymentMethodName;
                                                var currencyName = " " + context.Money.Where(mn => mn.HotelId == user.HotelId && mn.MoneyId == (int)obj["moneyId"]).FirstOrDefault().MoneyName;
                                                info.Particular.Add("DESCRIPTION", (string)obj["paymentDescription"]);
                                                info.Particular.Add("CHARGE", String.Format("{0:n0}", (decimal)obj["amount"]) + currencyName + "(" + paymentMethodName + ")");
                                                returnResult.Add(info);
                                                break;

                                            case "ADD_MINIBAR":
                                            case "ADD_LAUNDRY":
                                            case "ADD_COMPENSATION":
                                                info.Id = (int)obj["roomExtraServiceNumber"];
                                                int roomExtraServiceId = (int)obj["roomExtraServiceId"];
                                                List<RoomExtraServiceItems> roomExtraServiceItems = context.RoomExtraServiceItems.Where(ri => ri.HotelId == user.HotelId && ri.RoomExtraServiceId == roomExtraServiceId).ToList();

                                                foreach (var esItem in roomExtraServiceItems)
                                                {
                                                    info.Particular.Add("(" + esItem.Quantity + ")" + context.ExtraServiceItems.Where(ei => ei.HotelId == user.HotelId && ei.ExtraServiceItemId == esItem.ExtraServiceItemId).FirstOrDefault().ExtraServiceItemName, (esItem.Quantity * esItem.Price).ToString());
                                                }
                                                returnResult.Add(info);
                                                break;

                                            case "ADD_EXTRA_SERVICE":
                                                info.Id = (int)obj["roomExtraServiceNumber"];
                                                int roomESId = (int)obj["roomExtraServiceId"];
                                                var roomESService = context.RoomExtraServices.Where(ri => ri.HotelId == user.HotelId && ri.RoomExtraServiceId == roomESId).FirstOrDefault();
                                                info.Particular.Add(roomESService.RoomExtraServiceDescription, roomESService.Amount.ToString());
                                                returnResult.Add(info);
                                                break;

                                            case "VOID_EXTRA_SERVICE":
                                                info.Id = (int)obj["roomExtraServiceNumber"];
                                                int roomESIdDeleted = (int)obj["roomExtraServiceId"];
                                                var roomESServiceDeleted = context.RoomExtraServices.Where(ri => ri.HotelId == user.HotelId && ri.RoomExtraServiceId == roomESIdDeleted).FirstOrDefault();
                                                info.Particular.Add(roomESServiceDeleted.RoomExtraServiceDescription, roomESServiceDeleted.Amount.ToString());
                                                info.Particular.Add("REASON", roomESServiceDeleted.DeletedReason);
                                                info.User = context.AspNetUsers.Where(us => us.DefaultHotelId == user.HotelId && us.Id == roomESServiceDeleted.DeletedBy).FirstOrDefault().UserName;
                                                info.DateTime = roomESServiceDeleted.DeletedDate ?? default(DateTime);
                                                returnResult.Add(info);
                                                break;

                                            case "CHECKIN":
                                            case "BOOKED":
                                                if (original.Property("reservationRoomId") == null || (string)original.Property("bookingStatus") == "BOOKED")
                                                {
                                                    var roomTemp = context.Rooms.Where(rm => rm.HotelId == user.HotelId && rm.RoomId == (int)obj["roomId"]).FirstOrDefault();
                                                    info.Id = reservation.ReservationNumber ?? 0;
                                                    info.RoomNo = roomTemp.RoomName;
                                                    info.Particular.Add("ROOM_NO", roomTemp.RoomName);
                                                    info.Particular.Add("ROOM_TYPE", roomType.RoomTypeName);
                                                    info.Particular.Add("PRICE_RATE", roomPrice.RoomPriceName + "(" + reservationRoom.Price + ")");
                                                    info.Particular.Add("ADULTS", reservationRoom.Adults.ToString());
                                                    info.Particular.Add("CHILDREN", reservationRoom.Child.ToString());
                                                    info.Particular.Add("ARRIVAL", reservationRoom.ArrivalDate.Value.AddMinutes(currentHotel.TimeZoneOffset).ToString(format));
                                                    info.Particular.Add("DEPARTURE", reservationRoom.DepartureDate.Value.AddMinutes(currentHotel.TimeZoneOffset).ToString(format));
                                                    info.Particular.Add("NOTE", reservationRoom.Note);
                                                    if (reservationRoom.Foc)
                                                    {
                                                        info.Particular.Add("", "FOC");
                                                    }
                                                    if (reservationRoom.DiscountFlat > 0)
                                                    {
                                                        info.Particular.Add("DISCOUNT_FLAT", reservationRoom.DiscountFlat.ToString());
                                                    }
                                                    if (reservationRoom.DiscountPercentage > 0)
                                                    {
                                                        info.Particular.Add("DISCOUNT_PERCENTAGE", reservationRoom.DiscountPercentage.ToString());
                                                    }

                                                }
                                                else
                                                {
                                                    var roomTemp = context.Rooms.Where(rm => rm.HotelId == user.HotelId && rm.RoomId == (int)obj["roomId"]).FirstOrDefault();
                                                    info.Id = reservation.ReservationNumber ?? 0;
                                                    info.RoomNo = roomTemp.RoomName;
                                                    info.Particular.Add("ROOM_NO", roomTemp.RoomName);
                                                    info.Particular.Add("ROOM_TYPE", roomType.RoomTypeName);
                                                    info.Particular.Add("PRICE_RATE", roomPrice.RoomPriceName + "(" + reservationRoom.Price + ")");
                                                    info.Particular.Add("ADULTS", reservationRoom.Adults.ToString());
                                                    info.Particular.Add("CHILDREN", reservationRoom.Child.ToString());
                                                    info.Particular.Add("ARRIVAL", reservationRoom.ArrivalDate.ToString());
                                                    info.Particular.Add("DEPARTURE", reservationRoom.DepartureDate.ToString());
                                                    info.Particular.Add("NOTE", reservationRoom.Note);
                                                    if (reservationRoom.Foc)
                                                    {
                                                        info.Particular.Add("", "FOC");
                                                    }
                                                    if (reservationRoom.DiscountFlat > 0)
                                                    {
                                                        info.Particular.Add("DISCOUNT_FLAT", reservationRoom.DiscountFlat.ToString());
                                                    }
                                                    if (reservationRoom.DiscountPercentage > 0)
                                                    {
                                                        info.Particular.Add("DISCOUNT_PERCENTAGE", reservationRoom.DiscountPercentage.ToString());
                                                    }
                                                }
                                                returnResult.Add(info);

                                                break;

                                            case "CHECKOUT":
                                                info.Id = reservation.ReservationNumber ?? 0;
                                                info.Particular.Add("", "CHECKOUT");
                                                returnResult.Add(info);
                                                break;
                                            case "CANCELLED":
                                                info.Id = reservation.ReservationNumber ?? 0;
                                                info.Particular.Add("REASON", reservationRoom.CancelReason);
                                                returnResult.Add(info);
                                                break;
                                            case "NOSHOW":
                                                info.Id = reservation.ReservationNumber ?? 0;
                                                info.Particular.Add("", "NOSHOW");
                                                returnResult.Add(info);
                                                break;

                                            case "AMEND_STAY":
                                                info.Id = reservation.ReservationNumber ?? 0;
                                                if (original.Property("arrivalDate") != null && original.Property("departureDate") != null)
                                                {
                                                    info.Particular.Add("OLD_STAY", ((DateTime)original["arrivalDate"]).ToString(format) + " -> " + ((DateTime)original["departureDate"]).ToString(format));
                                                }
                                                if (obj.Property("arrivalDate") != null && obj.Property("departureDate") != null)
                                                {
                                                    info.Particular.Add("NEW_STAY", ((DateTime)obj["arrivalDate"]).ToString(format) + " -> " + ((DateTime)obj["departureDate"]).ToString(format));
                                                }
                                                if (obj.Property("adults") != null)
                                                {
                                                    info.Particular.Add("ADULTS", (string)obj.Property("adults"));
                                                }
                                                if (obj.Property("child") != null)
                                                {
                                                    info.Particular.Add("CHILDREN", (string)obj.Property("child"));
                                                }
                                                returnResult.Add(info);
                                                break;




                                        }
                                    }
                                    else// ALL VOID CASE + ROOM MOVE + PAST CHECKOUT
                                    {

                                        if (obj.Property("isDeleted") != null && obj.Property("roomExtraServiceId") != null)
                                        {
                                            if ((bool)obj.Property("isDeleted") == true)
                                            {
                                                info.User = auditUserName;
                                                info.DateTime = auditDateTime;

                                                int roomESId = (int)obj["roomExtraServiceId"];
                                                info.Id = context.RoomExtraServices.Where(re => re.HotelId == user.HotelId && re.RoomExtraServiceId == roomESId).FirstOrDefault().RoomExtraServiceNumber ?? 0;
                                                int roomExtraServiceItemId = (int)obj["roomExtraServiceItemId"];
                                                var roomExtraServiceItem = context.RoomExtraServiceItems.Where(ri => ri.HotelId == user.HotelId && ri.RoomExtraServiceItemId == roomExtraServiceItemId).FirstOrDefault();
                                                switch (operation)
                                                {
                                                    case "VOID_MINIBAR":
                                                    case "VOID_LAUNDRY":
                                                    case "VOID_COMPENSATION":
                                                        info.Particular.Add("(" + roomExtraServiceItem.Quantity + ")" + context.ExtraServiceItems.Where(ei => ei.HotelId == user.HotelId && ei.ExtraServiceItemId == roomExtraServiceItem.ExtraServiceItemId).FirstOrDefault().ExtraServiceItemName, (roomExtraServiceItem.Quantity * roomExtraServiceItem.Price).ToString());
                                                        info.Particular.Add("REASON", roomExtraServiceItem.DeletedReason);
                                                        returnResult.Add(info);
                                                        break;

                                                }

                                            }
                                        }
                                        else if (obj.Property("roomMoveId") != null)
                                        {
                                            switch (operation)
                                            {
                                                case "ROOM_MOVE":
                                                    if (obj.Property("oldRoomId") != null)
                                                    {
                                                        info.Id = reservation.ReservationNumber ?? 0;
                                                        var oldRoom = context.Rooms.Where(rm => rm.HotelId == user.HotelId && rm.RoomId == (int)obj["oldRoomId"]).FirstOrDefault();
                                                        var oldRoomType = context.RoomTypes.Where(rt => rt.HotelId == user.HotelId && rt.RoomTypeId == oldRoom.RoomTypeId).FirstOrDefault();
                                                        var oldRoomPrice = context.RoomPrices.Where(rp => rp.HotelId == user.HotelId && rp.RoomTypeId == oldRoomType.RoomTypeId && rp.RoomPriceId == (int)obj["oldRoomPriceId"]).FirstOrDefault();
                                                        var newRoom = context.Rooms.Where(rm => rm.HotelId == user.HotelId && rm.RoomId == (int)obj["newRoomId"]).FirstOrDefault();
                                                        var newRoomType = context.RoomTypes.Where(rt => rt.HotelId == user.HotelId && rt.RoomTypeId == newRoom.RoomTypeId).FirstOrDefault();
                                                        var newRoomPrice = context.RoomPrices.Where(rp => rp.HotelId == user.HotelId && rp.RoomTypeId == newRoomType.RoomTypeId && rp.RoomPriceId == (int)obj["newRoomPriceId"]).FirstOrDefault();
                                                        info.Particular.Add("OLD_ROOM", oldRoom.RoomName + "(" + oldRoomType.RoomTypeName + ") - " + oldRoomPrice.RoomPriceName);
                                                        info.Particular.Add("NEW_ROOM", newRoom.RoomName + "(" + newRoomType.RoomTypeName + ") - " + newRoomPrice.RoomPriceName);

                                                        returnResult.Add(info);
                                                    }

                                                    break;
                                            }
                                            //}

                                        }
                                        else if (obj.Property("pastCheckOutId") != null)
                                        {
                                            switch (operation)
                                            {
                                                case "PAST_CHECKOUT":
                                                    info.Id = reservation.ReservationNumber ?? 0;
                                                    info.Particular.Add("ARRIVAL", reservationRoom.ArrivalDate.Value.ToString(format));
                                                    info.Particular.Add("DEPARTURE", reservationRoom.DepartureDate.Value.ToString(format));
                                                    info.Particular.Add("PAST_CHECKOUT_DEPARTURE", ((DateTime)obj["pastCheckOutTime"]).ToString(format));
                                                    info.Particular.Add("REASON", (string)obj["pastCheckOutReason"]);
                                                    returnResult.Add(info);
                                                    break;
                                            }
                                        }
                                        else if (obj.Property("changeReservationStatusId") != null)
                                        {
                                            switch (operation)
                                            {
                                                case "PRE_CHECKIN":
                                                    info.Id = reservation.ReservationNumber ?? 0;
                                                    info.Particular.Add("PRE_CHECKIN", "CHANGE_RESERVATION_STATUS_FROM_CHECKIN_TO_BOOKED");
                                                    info.Particular.Add("REASON", (string)obj["reason"]);
                                                    returnResult.Add(info);
                                                    break;
                                                case "PRE_CHECKOUT":
                                                    info.Id = reservation.ReservationNumber ?? 0;
                                                    info.Particular.Add("PRE_CHECKOUT", "CHANGE_RESERVATION_STATUS_FROM_CHECKOUT_TO_CHECKIN");
                                                    info.Particular.Add("REASON", (string)obj["reason"]);
                                                    returnResult.Add(info);
                                                    break;
                                            }
                                        }
                                    }



                                }
                            }
                        }
                        else if (numberCount > 1) // ROOM_MOVE, CANCELLED
                        {
                            var reservationRoom = new ReservationRooms();
                            foreach (var entity in item.Entities)
                            {
                                JObject entityObject = JObject.Parse(entity.Current.ToString());
                                if (entityObject.Property("reservationRoomId") != null)
                                {
                                    reservationRoom = context.ReservationRooms.Where(rr => rr.HotelId == user.HotelId && rr.ReservationRoomId == (int)entityObject["reservationRoomId"]).FirstOrDefault();

                                }
                            }
                            var reservation = context.Reservations.Where(r => r.HotelId == user.HotelId && r.ReservationId == reservationRoom.ReservationId).FirstOrDefault();
                            var room = context.Rooms.Where(rm => rm.HotelId == user.HotelId && rm.RoomId == reservationRoom.RoomId).FirstOrDefault();
                            var roomType = context.RoomTypes.Where(rt => rt.HotelId == user.HotelId && rt.RoomTypeId == reservationRoom.RoomTypeId).FirstOrDefault();
                            var roomPrice = context.RoomPrices.Where(rp => rp.HotelId == user.HotelId && rp.RoomPriceId == reservationRoom.RoomPriceId).FirstOrDefault();
                            var traveller = context.Travellers.Where(tvl => tvl.TravellerId == (context.ReservationTravellers.Where(rt => rt.ReservationRoomId == reservationRoom.ReservationRoomId && rt.TravellerId == reservationRoom.TravellerId).FirstOrDefault().TravellerId)).FirstOrDefault();

                            AuditLogInformation info = new AuditLogInformation();
                            info.ReservationNumber = reservation.ReservationNumber ?? 0;
                            info.Id = reservation.ReservationNumber ?? 0;
                            info.RoomNo = room.RoomName;
                            info.Guest = traveller.Fullname;
                            info.Operation = operation;
                            info.Particular = new Dictionary<string, string>();
                            info.User = auditUserName;
                            info.DateTime = auditDateTime;

                            foreach (var entity in item.Entities)
                            {
                                JObject original = new JObject();
                                if (entity.Original != null)
                                {
                                    original = JObject.Parse(entity.Original.ToString());
                                }
                                JObject obj = JObject.Parse(entity.Current.ToString());
                                if (obj.Property("paymentId") != null && operation == "ADD_PAYMENT")
                                {
                                    AuditLogInformation info2 = new AuditLogInformation();
                                    info2.ReservationNumber = reservation.ReservationNumber ?? 0;
                                    info2.Id = reservation.ReservationNumber ?? 0;
                                    info2.RoomNo = room.RoomName;
                                    info2.Guest = traveller.Fullname;
                                    info2.Operation = operation;
                                    info2.Particular = new Dictionary<string, string>();
                                    info2.User = auditUserName;
                                    info2.DateTime = auditDateTime;
                                    info2.Id = (int)obj["paymentNumber"];
                                    info2.Particular.Add("DESCRIPTION", (string)obj["paymentDescription"]);
                                    info2.Particular.Add("CHARGE", (string)obj["amount"]);
                                    returnResult.Add(info2);
                                }
                                else
                                {
                                    switch (operation)
                                    {
                                        case "ROOM_MOVE":
                                            if (obj.Property("oldRoomId") != null)
                                            {
                                                var oldRoom = context.Rooms.Where(rm => rm.HotelId == user.HotelId && rm.RoomId == (int)obj["oldRoomId"]).FirstOrDefault();
                                                var oldRoomType = context.RoomTypes.Where(rt => rt.HotelId == user.HotelId && rt.RoomTypeId == oldRoom.RoomTypeId).FirstOrDefault();
                                                var oldRoomPrice = context.RoomPrices.Where(rp => rp.HotelId == user.HotelId && rp.RoomTypeId == oldRoomType.RoomTypeId && rp.RoomPriceId == (int)obj["oldRoomPriceId"]).FirstOrDefault();
                                                var newRoom = context.Rooms.Where(rm => rm.HotelId == user.HotelId && rm.RoomId == (int)obj["newRoomId"]).FirstOrDefault();
                                                var newRoomType = context.RoomTypes.Where(rt => rt.HotelId == user.HotelId && rt.RoomTypeId == newRoom.RoomTypeId).FirstOrDefault();
                                                var newRoomPrice = context.RoomPrices.Where(rp => rp.HotelId == user.HotelId && rp.RoomTypeId == newRoomType.RoomTypeId && rp.RoomPriceId == (int)obj["newRoomPriceId"]).FirstOrDefault();
                                                info.Particular.Add("OLD_ROOM", oldRoom.RoomName + "(" + oldRoomType.RoomTypeName + ") - " + oldRoomPrice.RoomPriceName);
                                                info.Particular.Add("NEW_ROOM", newRoom.RoomName + "(" + newRoomType.RoomTypeName + ") - " + newRoomPrice.RoomPriceName);
                                            }


                                            if (obj.Property("roomExtraServiceId") != null)
                                            {
                                                //var roomMoveFee = (decimal)obj["amount"];
                                                info.Particular.Add("ROOM_MOVE_FEE", String.Format("{0:n0}", (decimal)obj["amount"]));
                                            }

                                            break;

                                        case "CANCELLED":
                                            if (obj.Property("reservationRoomId") != null && obj.Property("reservationRoomNumber") != null)
                                            {
                                                info.Particular.Add("REASON", (string)obj["cancelReason"]);
                                            }

                                            if (obj.Property("paymentId") != null && obj.Property("paymentTypeName") != null && (string)obj.Property("paymentTypeName") == "NEW_PAYMENT")
                                            {
                                                var cancelFee = (decimal)obj["amount"];
                                                info.Particular.Add("CANCEL_FEE", cancelFee.ToString());
                                            }
                                            break;
                                    }
                                }

                            }
                            if (operation == "ROOM_MOVE" || operation == "CANCELLED")
                            {
                                returnResult.Add(info);
                            }
                        }
                    }
                }
            }
            return returnResult;
        }

        public List<AuditLogInformation> resolveSearchConfigurationResult(AuditTrailSearchModel model, string operation)
        {

            var user = Common.UserUtitily.getUserProfile();
            var currentHotel = context.Hotels.Where(ht => ht.HotelId == user.HotelId).FirstOrDefault();
            var node = new Uri("http://localhost:9200");
            var settings = new ConnectionSettings(
                    node,
                    defaultIndex: ConfigurationSettings.AppSettings["elasticIndex"]
                );
            var client = new ElasticClient(settings);

            var searchDescriptor = new SearchDescriptor<AuditLog>();
            searchDescriptor.Index(ConfigurationSettings.AppSettings["elasticIndex"]).Types("auditlogs").From(0).Size(1000);
            var filters = new List<FilterContainer>();
            filters.Add(new FilterDescriptor<AuditLog>().Term("entities.current.hotelId", user.HotelId));

            // SEARCH FOR FROM-TO
            var timeZoneOffset = -currentHotel.TimeZoneOffset / 60;
            TimeSpan offSet = new TimeSpan(timeZoneOffset, 0, 0);
            if (model.From == null)
            {
                model.From = ((DateTime)SqlDateTime.MinValue).Date;
            }
            if (model.To == null)
            {
                model.To = ((DateTime)SqlDateTime.MaxValue).Date;
            }
            if (model.From != null)
            {
                DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.From).Year, ((DateTime)model.From).Month, ((DateTime)model.From).Day, ((DateTime)model.From).Hour, ((DateTime)model.From).Minute, ((DateTime)model.From).Second, offSet).ToOffset(TimeSpan.Zero);
                //model.From = fromTemp.Date;
                model.From = model.From.AddHours(currentHotel.TimeZoneOffset / 60).Date;
            }
            if (model.To != null)
            {
                DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.To).Year, ((DateTime)model.To).Month, ((DateTime)model.To).Day, ((DateTime)model.To).Hour, ((DateTime)model.To).Minute, ((DateTime)model.To).Second, offSet).ToOffset(TimeSpan.Zero);
                //model.To = toTemp.Date;
                model.To = model.To.AddHours(currentHotel.TimeZoneOffset / 60).Date.AddDays(1);
            }

            filters.Add(new FilterDescriptor<AuditLog>().Range(r => r.OnField(f => f.Date).GreaterOrEquals(model.From).LowerOrEquals(model.To)));

            // SEARCH FOR USER
            var userName = "";
            QueryContainer userQuery = new QueryContainer();
            if (model.UserId != null)
            {
                var userTemp = context.AspNetUsers.Where(u => u.DefaultHotelId == user.HotelId && u.Id == model.UserId).FirstOrDefault();
                if (userTemp != null)
                {
                    userName = userTemp.UserName;
                    filters.Add(new FilterDescriptor<AuditLog>().Bool(b => b.Must(m => m.Query(q => q.Match(mat => mat.OnField(z => z.Username).Query(userName))))));
                }
            }

            switch (operation)
            {
                case "HOTEL_OWNER_INFORMATION":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.hotelOwnerId"));
                    break;
                case "HOTEL_INFORMATION_CHANGE":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.hotelName"));
                    break;
                case "ROOM_TYPE_CHANGE":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.roomTypeName"));
                    break;
                case "ROOM_CHANGE":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.roomName"));
                    break;
                case "ROOM_REPAIR_CHANGE":
                    filters.Add(new FilterDescriptor<AuditLog>().Bool(bq => bq.Should(shd => shd.Query(q => q.Match(m => m.OnField("entities.properties.name").Query("repairStartDate"))), shd => shd.Query(q => q.Match(m => m.OnField("entities.properties.name").Query("repairEndDate"))))));
                    break;
                case "STAFF_CHANGE":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.staffName"));
                    break;
                case "EXTRA_SERVICES_CHANGE":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.extraServiceCategoryId"));
                    break;
                case "PRICE_CHANGE":
                    filters.Add(new FilterDescriptor<AuditLog>().Exists("entities.current.roomPriceId"));
                    break;

            }
            searchDescriptor.Filter(f => f.And(filters.ToArray()));
            searchDescriptor.SortDescending("date");
            var search = client.Search<AuditLog>(
                   searchDescriptor
               );
            var result = search.Documents;
            List<AuditLogInformation> returnResult = new List<AuditLogInformation>();
            if (result.Count() > 0)
            {
                string format = "dd/MM/yyyy, hh:mm";
                foreach (var item in result)
                {
                    var auditUserName = item.Username;
                    var auditDateTime = item.Date;
                    AuditLogInformation info = new AuditLogInformation();
                    info.Operation = operation;
                    info.Particular = new Dictionary<string, string>();
                    info.User = auditUserName;
                    info.DateTime = auditDateTime;
                    if (item.Entities != null && item.Entities.Count > 0 && item.Entities.First().Properties != null && item.Entities.First().Properties.Count > 0)
                    {
                        var editHotelString = new List<String>();
                        var editRoomTypeString = new List<String>();
                        var editRoomString = new List<String>();
                        var ratePriorityString = new List<String>();
                        var hourlyPriceString = new List<String>();
                        var earlyCheckInDayNightString = new List<String>();
                        var overDueDayNightString = new List<String>();
                        var earlyCheckInFullDayString = new List<String>();
                        var overDueFullDayString = new List<String>();
                        var d_hourlyPriceString = new List<String>();
                        var d_earlyCheckInDayNightString = new List<String>();
                        var d_overDueDayNightString = new List<String>();
                        var d_earlyCheckInFullDayString = new List<String>();
                        var d_overDueFullDayString = new List<String>();
                        foreach (var entity in item.Entities)
                        {
                            JObject original = new JObject();
                            if (entity.Original != null)
                            {
                                original = JObject.Parse(entity.Original.ToString());
                            }
                            JObject obj = JObject.Parse(entity.Current.ToString());
                            
                            switch (operation)
                            {
                                
                                case "PRICE_CHANGE":
                                    
                                    //Room Price
                                    if (entity.Keys.First().Name == "RoomPriceId")
                                    {
                                        
                                        if (entity.Action == AuditAction.Insert)
                                        {
                                            info.Particular.Add("ADD_NEW_RATE", (string)obj["roomPriceName"]);
                                        }
                                        else
                                        {
                                            if (original != null)
                                            {
                                                if ((bool)original["isActive"] != (bool)obj["isActive"])
                                                {
                                                    string currentRoomPrice = (string)obj["roomPriceName"];
                                                    string oldString = (bool)original["isActive"] == true ? "ACTIVE" : "INACTIVE";
                                                    string newString = (bool)obj["isActive"] == true ? "ACTIVE" : "INACTIVE";
                                                    info.Particular.Add("CHANGE_RATE_STATUS", currentRoomPrice + " (" + oldString + " -> " + newString + ")");
                                                }
                                                else
                                                {
                                                    if ((int)original["priority"] != (int)obj["priority"])
                                                    {
                                                        string currentRoomPrice = (string)obj["roomPriceName"];
                                                        string oldString = ((int)original["priority"] + 1).ToString();
                                                        string newString = ((int)obj["priority"] + 1).ToString();
                                                        ratePriorityString.Add(currentRoomPrice + " (" + oldString + " -> " + newString + ")");
                                                    }
                                                    else
                                                    {
                                                        foreach(var prop in entity.Properties)
                                                        {
                                                            if (prop.Name.StartsWith("Use"))
                                                            {
                                                                info.Particular.Add("CHANGE_POLICY", prop.Name + "(" + prop.Original + " -> " + prop.Current + ")");
                                                            }
                                                            else
                                                            {
                                                                info.Particular.Add("EDIT_RATE", prop.Name + "(" + prop.Original + " -> " + prop.Current + ")");
                                                            }
                                                            
                                                        }
                                                        //info.Particular.Add("EDIT_RATE", entity.Properties.First().Name + "(" + item.Entities.First().Properties.First().Original + " -> " + item.Entities.First().Properties.First().Current + ")");
                                                    }
                                                }
                                            }
                                            
                                        }
                                    }
                                    else
                                    {
                                        if (entity.Action == AuditAction.Insert)
                                        {
                                            var value = obj["numberOfHour"] + " HOUR(S) - " + obj["price"];
                                            if ((string)obj["adjustmentCode"] == "HOURLY_PRICE")
                                            {
                                                hourlyPriceString.Add(value);
                                            }
                                            if ((string)obj["adjustmentCode"] == "EARLY_CHECKIN_DAY_NIGHT")
                                            {
                                                earlyCheckInDayNightString.Add(value);
                                            }
                                            if ((string)obj["adjustmentCode"] == "EARLY_CHECKIN_FULL_DAY")
                                            {
                                                earlyCheckInFullDayString.Add(value);
                                            }
                                            if ((string)obj["adjustmentCode"] == "OVERDUE_DAYNIGHT")
                                            {
                                                overDueDayNightString.Add(value);
                                            }
                                            if ((string)obj["adjustmentCode"] == "OVERDUE_FULLDAY")
                                            {
                                                overDueFullDayString.Add(value);
                                            }
                                            //hourlyPriceString.Add(value);
                                            //info.Particular.Add("ADD_NEW_RATE_" + (string)obj["adjustmentCode"], value);
                                        }
                                        if (entity.Action == AuditAction.Delete)
                                        {
                                            var value = obj["numberOfHour"] + " HOUR(S) - " + obj["price"];
                                            if ((string)obj["adjustmentCode"] == "HOURLY_PRICE")
                                            {
                                                d_hourlyPriceString.Add(value);
                                            }
                                            if ((string)obj["adjustmentCode"] == "EARLY_CHECKIN_DAY_NIGHT")
                                            {
                                                d_earlyCheckInDayNightString.Add(value);
                                            }
                                            if ((string)obj["adjustmentCode"] == "EARLY_CHECKIN_FULL_DAY")
                                            {
                                                d_earlyCheckInFullDayString.Add(value);
                                            }
                                            if ((string)obj["adjustmentCode"] == "OVERDUE_DAYNIGHT")
                                            {
                                                d_overDueDayNightString.Add(value);
                                            }
                                            if ((string)obj["adjustmentCode"] == "OVERDUE_FULLDAY")
                                            {
                                                d_overDueFullDayString.Add(value);
                                            }
                                            //hourlyPriceString.Add(value);
                                            //info.Particular.Add("ADD_NEW_RATE_" + (string)obj["adjustmentCode"], value);
                                        }
                                    }
                                    
                                    break;
                                case "HOTEL_OWNER_INFORMATION":
                                    info.Particular.Add(entity.Properties.First().Name, item.Entities.First().Properties.First().Original + " -> " + item.Entities.First().Properties.First().Current);
                                    break;
                                case "HOTEL_INFORMATION_CHANGE":
                                    foreach (var prop in entity.Properties)
                                    {
                                        editHotelString.Add(prop.Name + "(" + prop.Original + " -> " + prop.Current + ")");
                                    }
                                    //info.Particular.Add(entity.Properties.First().Name, item.Entities.First().Properties.First().Original + " -> " + item.Entities.First().Properties.First().Current);
                                    break;
                                case "ROOM_TYPE_CHANGE":
                                    if (entity.Action == AuditAction.Insert)
                                    {
                                        info.Particular.Add("ADD_NEW_ROOM_TYPE", (string)obj["roomTypeName"]);
                                    }
                                    else
                                    {
                                        if (original != null)
                                        {
                                            if ((bool)original["isHidden"] != (bool)obj["isHidden"])
                                            {
                                                string currentRoomType = (string)obj["roomTypeName"];
                                                string oldString = (bool)original["isHidden"] == true ? "INACTIVE" : "ACTIVE";
                                                string newString = (bool)obj["isHidden"] == true ? "INACTIVE" : "ACTIVE";
                                                info.Particular.Add("CHANGE_ROOM_TYPE_STATUS", currentRoomType + " (" + oldString + " -> " + newString + ")");
                                            }
                                            else
                                            {
                                                foreach (var prop in entity.Properties)
                                                {
                                                    editRoomTypeString.Add(prop.Name + "(" + prop.Original + " -> " + prop.Current + ")");
                                                }
                                               // info.Particular.Add("EDIT_ROOM_TYPE", entity.Properties.First().Name + "(" + item.Entities.First().Properties.First().Original + " -> " + item.Entities.First().Properties.First().Current + ")");
                                            }
                                        }
                                    }
                                    break;

                                case "ROOM_CHANGE":
                                    if (entity.Action == AuditAction.Insert)
                                    {
                                        info.Particular.Add("ADD_NEW_ROOM", (string)obj["roomName"]);
                                    }
                                    else
                                    {
                                        if (original != null)
                                        {
                                            if ((bool)original["isHidden"] != (bool)obj["isHidden"])
                                            {
                                                string currentRoom = (string)obj["roomName"];
                                                string oldString = (bool)original["isHidden"] == true ? "INACTIVE" : "ACTIVE";
                                                string newString = (bool)obj["isHidden"] == true ? "INACTIVE" : "ACTIVE";
                                                info.Particular.Add("CHANGE_ROOM_STATUS", currentRoom + " (" + oldString + " -> " + newString + ")");
                                            }
                                            else
                                            {
                                                foreach (var prop in entity.Properties)
                                                {
                                                    editRoomString.Add(prop.Name + "(" + prop.Original + " -> " + prop.Current + ")");
                                                }
                                                //info.Particular.Add("EDIT_ROOM", entity.Properties.First().Name + "(" + item.Entities.First().Properties.First().Original + " -> " + item.Entities.First().Properties.First().Current + ")");
                                            }
                                        }
                                    }
                                    break;
                                case "ROOM_REPAIR_CHANGE":
                                    info.Particular.Add("ROOM_NAME", (string)obj["roomName"]);
                                    if (original["houseStatus"] == null)
                                    {
                                        if ((string)obj["houseStatus"] == "REPAIR")
                                        {
                                            info.Particular.Add("START_REPAIRING", ((DateTime)obj["repairStartDate"]).ToString(format) + " -> " + ((DateTime)obj["repairEndDate"]).ToString(format));
                                        }
                                    }
                                    else
                                    {
                                        if ((string)obj["houseStatus"] == "REPAIR")
                                        {
                                            info.Particular.Add("OLD_REPAIR_TIME", ((DateTime)original["repairStartDate"]).ToString(format) + " -> " + ((DateTime)original["repairEndDate"]).ToString(format));
                                            info.Particular.Add("NEW_REPAIR_TIME", ((DateTime)obj["repairStartDate"]).ToString(format) + " -> " + ((DateTime)obj["repairEndDate"]).ToString(format));
                                        }
                                        else
                                        {
                                            info.Particular.Add("FINISH_REPARING", "HOUSE_STATUS_SET_TO_AVAILABLE");
                                        }

                                    }

                                    break;

                                case "STAFF_CHANGE":
                                    if (entity.Action == AuditAction.Insert)
                                    {
                                        info.Particular.Add("ADD_NEW_STAFF", (string)obj["staffName"]);
                                    }
                                    else
                                    {
                                        info.Particular.Add(entity.Properties.First().Name, item.Entities.First().Properties.First().Original + " -> " + item.Entities.First().Properties.First().Current);
                                    }

                                    break;
                                case "EXTRA_SERVICES_CHANGE":
                                    if (entity.Action == AuditAction.Insert)
                                    {
                                        if (entity.Keys.First().Name == "ExtraServiceCategoryId")
                                        {
                                            info.Particular.Add("ADD_NEW_CATEGORY", (string)obj["extraServiceCategoryName"]);
                                        }
                                        if (entity.Keys.First().Name == "ExtraServiceItemId")
                                        {
                                            var extraServiceCategory = context.ExtraServiceCategories.Where(cat => cat.HotelId == user.HotelId && cat.ExtraServiceCategoryId == (int)obj.Property("extraServiceCategoryId")).FirstOrDefault();
                                            var extraServiceCategoryName = "";
                                            if (extraServiceCategory != null)
                                            {
                                                extraServiceCategoryName = extraServiceCategory.ExtraServiceCategoryName;
                                                info.Particular.Add("ADD_NEW_ITEM", (string)obj["extraServiceItemName"] + "(" + extraServiceCategoryName + ")");
                                            }
                                            else
                                            {
                                                info.Particular.Add("ADD_NEW_ITEM", (string)obj["extraServiceItemName"]);
                                            }
                                        }
                                    }
                                    else if (entity.Action == AuditAction.Update)
                                    {
                                        var flag = "";
                                        if (obj["extraServiceCategoryName"] != null)
                                        {
                                            flag = (string)obj["extraServiceCategoryName"];
                                        }
                                        if (obj["extraServiceItemName"] != null)
                                        {
                                            flag = (string)obj["extraServiceItemName"];
                                        }
                                        if ((bool)original["isHidden"] != (bool)obj["isHidden"])
                                        {
                                            string oldString = (bool)original["isHidden"] == true ? "INACTIVE" : "ACTIVE";
                                            string newString = (bool)obj["isHidden"] == true ? "INACTIVE" : "ACTIVE";
                                            info.Particular.Add("CHANGE_STATUS", flag + " (" + oldString + " -> " + newString + ")");
                                        }
                                        else
                                        {
                                            //info.Particular.Add("EDIT_ROOM", entity.Properties.First().Name + "(" + item.Entities.First().Properties.First().Original + " -> " + item.Entities.First().Properties.First().Current + ")");
                                            info.Particular.Add(entity.Properties.First().Name, item.Entities.First().Properties.First().Original + " -> " + item.Entities.First().Properties.First().Current);
                                        }
                                    }
                                    else if (entity.Action == AuditAction.Delete)
                                    {
                                        if (obj["extraServiceCategoryName"] != null)
                                        {
                                            info.Particular.Add("DELETED_CATEGORY", (string)obj["extraServiceCategoryName"]);
                                        }
                                        if (obj["extraServiceItemName"] != null)
                                        {
                                            info.Particular.Add("DELETED_ITEM", (string)obj["extraServiceItemName"]);
                                        }
                                    }
                                    break;
                            }

                        }

                        if (editHotelString.Count() > 0)
                        {
                            var values = String.Join(", ", editHotelString);
                            info.Particular.Add("EDIT_HOTEL", values);
                        }
                        if (ratePriorityString.Count() > 0)
                        {
                            var values = String.Join(", ", ratePriorityString);
                            info.Particular.Add("CHANGE_RATE_PRIORITY", values);
                        }
                        if (editRoomTypeString.Count() > 0)
                        {
                            var values = String.Join(", ", editRoomTypeString);
                            info.Particular.Add("EDIT_ROOM_TYPE", values);
                        }
                        if (editRoomString.Count() > 0)
                        {
                            var values = String.Join(", ", editRoomString);
                            info.Particular.Add("EDIT_ROOM", values);
                        }

                        if (hourlyPriceString.Count() > 0)
                        {
                            IEnumerable<string> difference = hourlyPriceString.Except(d_hourlyPriceString);
                            if (difference.Count() > 0)
                            {
                                var values = String.Join(", ", difference);
                                info.Particular.Add("NEW_HOURLY_PRICE", values);
                            }
                        }

                        if (earlyCheckInFullDayString.Count() > 0)
                        {
                            IEnumerable<string> difference = earlyCheckInFullDayString.Except(d_earlyCheckInFullDayString);
                            if (difference.Count() > 0)
                            {
                                var values = String.Join(", ", difference);
                                info.Particular.Add("NEW_EARLY_CHECKIN_FULL_DAY", values);
                            }
                        }
                        if (overDueFullDayString.Count() > 0)
                        {
                            IEnumerable<string> difference = overDueFullDayString.Except(d_overDueFullDayString);
                            if (difference.Count() > 0)
                            {
                                var values = String.Join(", ", difference);
                                info.Particular.Add("NEW_OVERDUE_FULL_DAY", values);
                            }
                        }
                        if (earlyCheckInDayNightString.Count() > 0)
                        {
                            IEnumerable<string> difference = earlyCheckInDayNightString.Except(d_earlyCheckInDayNightString);
                            if (difference.Count() > 0)
                            {
                                var values = String.Join(", ", difference);
                                info.Particular.Add("NEW_EARLY_CHECKIN_DAY_NIGHT", values);
                            }
                        }
                        if (overDueDayNightString.Count() > 0)
                        {
                            IEnumerable<string> difference = overDueDayNightString.Except(d_overDueDayNightString);
                            if (difference.Count() > 0)
                            {
                                var values = String.Join(", ", difference);
                                info.Particular.Add("NEW_OVERDUE_DAY_NIGHT", values);
                            }
                        }

                        returnResult.Add(info);
                    }

                }
            }
            return returnResult;
        }
    }
}